/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include "core/设备内存缓存.h"
#include "../Vulkan框架.h"


typedef struct {
	VkDevice				m_设备;
	VkBuffer				m_Buf;
	VkDeviceMemory			m_Mem;
	VkDescriptorBufferInfo	m_Buffer_info;
}S_VkBuffer;


Inline S_物理设备属性* f_vk_get物理设备属性(S_设备环境& ctx) {
	return (S_物理设备属性*)ctx.m_物理设备.pNext;
}



inline uint32 f_内存类型索引(VkPhysicalDeviceMemoryProperties& info, uint32_t typeBits, VkFlags requirements_mask) {
	for (uint32 i = 0; i < info.memoryTypeCount; i++) {
		if ((typeBits & 1) == 1) {
			// Type is available, does it match user properties?
			if ((info.memoryTypes[i].propertyFlags & requirements_mask) == requirements_mask) {
				return i;
			}
		}
		typeBits >>= 1;
	}
	// No memory types matched, return failure
	return 0xffffffff;
}


Inline uint32 f_getVk缓存类型(uint32 type) {
	uint32 flags = 0;
	if (type & E_板载缓存类型::e_VBO) flags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
	if (type & E_板载缓存类型::e_UBO) flags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
	//if (type & E_板载缓存类型::e_TBOs) flags |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
	//if (type & E_板载缓存类型::e_TBOd) flags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
	if (type & E_板载缓存类型::e_SSBO) flags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
	if (type & E_板载缓存类型::e_SSBOd) flags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
	if (type & E_板载缓存类型::e_INDEX) flags |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
	if (type & E_板载缓存类型::e_INDIRECT) flags |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
	//if (type & E_板载缓存类型::e_DI) flags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
	if (type & E_板载缓存类型::e_IMAGE) flags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
	if (type & E_板载缓存类型::e_IMAGE_SAMPLER) flags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
	if (type & E_板载缓存类型::e_光追BVH) flags |= VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
	if (type & E_板载缓存类型::e_光追实例) flags |= VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
	if (type & E_板载缓存类型::e_光追顶层加速结构) flags |= VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR;
	if (type & E_板载缓存类型::e_光追底层加速结构) flags |= VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR;
	if (type & E_板载缓存类型::e_着色列表) flags |= VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
	if (type & E_板载缓存类型::e_着色端内存地址) flags |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
	return flags;
}



struct S_VkArray缓存 : public S_板载缓存 {
	S_VkBuffer		m_Data;
	VkBufferUsageFlags m_VkBufferUsageFlags;
	VkAccelerationStructureKHR	m_光追加速结构;

	

	S_VkArray缓存(S_设备环境& ctx, uint16 offset = 1, E_板载缓存类型 type = E_板载缓存类型::e_VBO, uint64 size = 0);
	S_VkArray缓存(S_设备环境& ctx, E_板载缓存类型 type, VkBufferUsageFlags typeflags, uint16 offset, uint64 size);
	~S_VkArray缓存();


	void	f_fillData(const void* data, uint64 bitSize);

	void	f_map() ;
	void	f_unmap() ;
	//uint32	f_count() { return m_Data.m_Buffer_info.range; }
	void	f_resize(uint64 bitSize);
	void	f_copy(S_结构对象指针 sObj);
	void	f_change板载缓存(E_板载缓存类型 memType);

private:
	uint32	f_分配(VkBufferUsageFlags type, uint64 BitSize);

};



Inline VkAccelerationStructureKHR& f_buf_get加速结构(S_板载缓存* buf) { return static_cast<S_VkArray缓存*>(buf)->m_光追加速结构; }
void* f_buf_get加速结构(S_GPU内存块索引& 块);


//VkAccelerationStructureKHR f_vkBuf_create加速结构(S_VkArray缓存* buf, VkAccelerationStructureTypeKHR type, VkAccelerationStructureBuildSizesInfoKHR buildSizeInfo);


Inline VkAccelerationStructureInstanceKHR* f_buf_实例加速结构_ptr(const S_GPU内存块索引& 块, uint32 offset = 0) {
	assert(块.m_Mem.m_大小);
	return &(((VkAccelerationStructureInstanceKHR*)块.m_Buf->m_mappedPtr)[块.m_Mem.m_偏移 + offset]);
}
Inline VkAccelerationStructureInstanceKHR& f_buf_实例加速结构_at(const S_GPU内存块索引& 块, uint32 offset = 0) {
	assert(offset < 块.m_Mem.m_大小);
	return (((VkAccelerationStructureInstanceKHR*)块.m_Buf->m_mappedPtr)[块.m_Mem.m_偏移 + offset]);
}




